package com.zwy.handler;


import com.zwy.constants.Const;
import com.zwy.constants.RespConst;
import com.zwy.domain.entity.LoginUser;
import com.zwy.domain.response.ResponseResult;
import com.zwy.domain.vo.AuthorizeVO;
import com.zwy.enums.RespEnum;
import com.zwy.service.UserService;
import com.zwy.utils.JwtUtils;
import com.zwy.utils.StringUtils;
import com.zwy.utils.WebUtil;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.List;
import java.util.UUID;

/**
 * @author zwy
 * @version 1.0
 * @description: SecurityHandler（结果播报器）
 * @date 2025/9/18 19:29
 */
@Component
public class SecurityHandler {
    @Resource
    private JwtUtils jwtUtils;
    @Resource
    private UserService userService;

    public static final String USER_NAME = "username";
    /**
     * 登录成功处理
     *
     * @param request        请求
     * @param response       响应
     * @param authentication 认证信息
     */
    public void onAuthenticationSuccess(
            HttpServletRequest request,
            HttpServletResponse response,
            Authentication authentication
    ) {
        handlerOnAuthenticationSuccess(request,response,(LoginUser)authentication.getPrincipal());
    }

    /**
     * 处理认证成功后的逻辑
     *
     * @param request  请求对象
     * @param response 响应对象
     * @param user     登录用户信息
     */
    public void handlerOnAuthenticationSuccess(
            HttpServletRequest request,
            HttpServletResponse response,
            LoginUser user
    ) {
        // 获取请求头中的客户端类型
        String typeHeader = request.getHeader(Const.TYPE_HEADER);

        // 验证请求合法性：如果请求头不匹配后台或前台请求，并且用户注册类型为1（第三方注册），则抛出异常
        if ((!StringUtils.matches(typeHeader, List.of(Const.BACKEND_REQUEST, Const.FRONTEND_REQUEST)) && user.getUser().getRegisterType() == 1)) {
            throw new BadCredentialsException("非法请求");
        }

        // 获取用户ID和用户名
        Long id = user.getUser().getId();
        String name = user.getUser().getUsername();

        // 生成UUID作为JWT的唯一标识符
        String uuid = UUID.randomUUID().toString();

        // 使用JWT工具类创建JWT令牌
        String token = jwtUtils.createJwt(uuid, user, id, name);

        // 构建返回给前端的授权信息VO对象
        AuthorizeVO authorizeVO = user.getUser().asViewObject(AuthorizeVO.class, v -> {
            v.setToken(token);                // 设置JWT令牌
            v.setExpire(jwtUtils.expireTime()); // 设置过期时间
        });

        // 更新用户登录状态
        userService.userLoginStatus(user.getUser().getId(), user.getUser().getRegisterType());


        // 将成功的响应结果以JSON格式写入响应流中
        WebUtil.renderString(response, ResponseResult.success(authorizeVO, RespConst.SUCCESS_LOGIN_MSG).asJsonString());
    }


    /**
     * 登录失败处理
     */
    public void onAuthenticationFailure(
            HttpServletRequest request,
            HttpServletResponse response,
            AuthenticationException exception
    ) throws IOException {

        WebUtil.renderString(response, ResponseResult.failure(RespEnum.USERNAME_OR_PASSWORD_ERROR.getCode(), exception.getMessage()).asJsonString());
    }

    /**
     * 退出登录处理
     */
    public void onLogoutSuccess(
            HttpServletRequest request,
            HttpServletResponse response,
            Authentication authentication
    ) {
        boolean invalidateJwt = jwtUtils.invalidateJwt(request.getHeader("Authorization"));
        if (invalidateJwt) {
            WebUtil.renderString(response, ResponseResult.success().asJsonString());
            return;
        }
        WebUtil.renderString(response, ResponseResult.failure(RespEnum.NOT_LOGIN.getCode(), RespEnum.NOT_LOGIN.getMsg()).asJsonString());
    }

    /**
     * 没有登录处理
     */
    public void onUnAuthenticated(
            HttpServletRequest request,
            HttpServletResponse response,
            AuthenticationException exception
    ) throws IOException {
        WebUtil.renderString(response, ResponseResult.failure(RespEnum.NOT_LOGIN.getCode(), RespEnum.NOT_LOGIN.getMsg()).asJsonString());
    }

    /**
     * 没有权限处理
     */
    public void onAccessDeny(
            HttpServletRequest request,
            HttpServletResponse response,
            AccessDeniedException exception
    ) {
        WebUtil.renderString(response, ResponseResult.failure(RespEnum.NO_PERMISSION.getCode(), RespEnum.NO_PERMISSION.getMsg()).asJsonString());
    }
}
